<?php

class content_mdl_article_nodes extends dbeav_model {

    public function strip_params_tags($params) {
        if ($params['seo_title'])
            $params['seo_title'] = htmlspecialchars($params['seo_title'], ENT_QUOTES);
        if ($params['seo_keywords'])
            $params['seo_keywords'] = htmlspecialchars($params['seo_keywords'], ENT_QUOTES);
        if ($params['seo_description'])
            $params['seo_description'] = htmlspecialchars($params['seo_description'], ENT_QUOTES);
        return $params;
    }
 // End Function
    public function format_params_pagename($params) {
        if (isset($params['node_pagename']) && empty($params['node_pagename'])) {
            $params['node_pagename'] = strtolower(preg_replace('([^0-9a-zA-Z])', '', implode('', kernel::single('content_py_base')->get_array($params['node_name'], 'utf-8'))));
        }
        return $params;
    }
 // End Function
    public function valid_insert($params) {
        if (empty($params['node_name'])) {
            trigger_error(app::get('content')->_('节点名称不能为空'), E_USER_ERROR);
            return false;
        }
        $params['parent_id'] = ($params['parent_id'] > 0) ? $params['parent_id'] : 0;
        $params['ordernum'] = ($params['ordernum'] > 0) ? $params['ordernum'] : 0;
        $params = $this->strip_params_tags($params);
        $params = $this->format_params_pagename($params);
        return $params;
    }
 // End Function
    public function valid_update($params) {
        $params = $this->strip_params_tags($params);
        $params = $this->format_params_pagename($params);
        return $params;
    }
 // End Function
    public function insert(&$params) {
        $params = $this->valid_insert($params);
        if (! $params)
            return false;
        $insert_id = parent::insert($params);
        if ($insert_id) {
            $this->upgrade_parent($insert_id);
            kernel::single('content_article_node')->delete_node_kvstore($insert_id); // todo: 清空kvstore值，以免冲突
            kernel::single('content_article_node')->store_nodes_change();
            return $this->update_node_path($insert_id); // 更新节点路径信息
        } else {
            return false;
        }
    }

    public function update($params, $filter = array(), $mustUpdate = null) {
        $params = $this->valid_update($params);
        if (! $params)
            return false;
        $rows = $this->getList('*', $filter);
        if (isset($params['parent_id'])) {
            $node_path_arr = array();
            if ($params['parent_id'] > 0) {
                $node_path = $this->select()
                    ->columns('node_path')
                    ->where('node_id = ?', $params['parent_id'])
                    ->instance()
                    ->fetch_one();
                if ($node_path) {
                    $node_path_arr = @explode(",", $node_path);
                }
            }
            foreach ($rows as $row) {
                if ($row['node_id'] == $params['parent_id']) {
                    trigger_error(app::get('content')->_('节点『') . $row['node_name'] . app::get('content')->_("』的父节点不能为自己"), E_USER_ERROR);
                    return false; // 父节点不能更新为自己，防止错误
                }
                if (in_array($row['node_id'], $node_path_arr)) {
                    trigger_error(app::get('content')->_('节点『') . $row['node_name'] . app::get('content')->_("』的父节点不能为自己的子节点"), E_USER_ERROR);
                    return false; // 父节点不能移动至自己的子节点，防止错误
                }
            }
        }
        $res = parent::update($params, $filter);
        if ($res) {
            foreach ($rows as $row) {
                if (isset($params['parent_id']) && $row['parent_id'] != $params['parent_id']) {
                    $this->upgrade_parent($row['node_id']);
                    $this->update_nodes_path($row['node_id']);
                    $this->update_node_path($row['parent_id']);
                }
                kernel::single('content_article_node')->delete_node_kvstore($row['node_id']); // todo: 清空kvstore值
            }
            kernel::single('content_article_node')->store_nodes_change();
            return true;
        } else {
            return false;
        }
    }

    public function delete($filter, $subSdf = 'delete') {
        $rows = $this->getList('*', $filter);
        foreach ($rows as $row) {
            if ($this->has_chilren($row['node_id'])) {
                trigger_error(app::get('content')->_("节点『") . $row['node_name'] . app::get('content')->_("』下存在子节点，不能删除"), E_USER_ERROR);
                return false; // 存在子节点
            }
        }
        $res = parent::delete($filter);
        if ($res) {
            foreach ($rows as $row) {
                if ($row['parent_id'] > 0) {
                    $this->update_node_path($row['parent_id']);
                }
                // $this->upgrade_parent($row['node_id']);
                kernel::single('content_article_node')->delete_node_kvstore($row['node_id']); // todo: 清空kvstore值
            }
            kernel::single('content_article_node')->store_nodes_change();
            return true;
        } else {
            return false;
        }
    }

    public function publish($pub = true, $filter) {
        $params = array(
            'ifpub' => ($pub) ? "true" : "false"
        );
        $oCAN = kernel::single("content_article_node");
        if (! $pub) { // 取消发布:同时取消子节点
            $aNodes = (array) $oCAN->get_nodes($filter['node_id']);
            foreach ($aNodes as $row) {
                if ($row['has_children'])
                    $this->publish($pub, array(
                        'node_id' => $row['node_id']
                    ));
            }
        } else { // 父节点未发布时禁止当前节点发布
            $aInfo = $oCAN->get_node($filter['node_id']);
            if ($aInfo['parent_id']) {
                $aParInfo = $oCAN->get_node($aInfo['parent_id']);
                if ($aParInfo['ifpub'] == 'false') {
                    return false;
                }
            }
        }
        
        return $this->update($params, $filter);
    }

    public function update_nodes_path($node_id) {
        if (empty($node_id))
            return false;
        $node_id = intval($node_id);
        $this->update_node_path($node_id);
        $rows = $this->select()
            ->columns('node_id')
            ->where('parent_id = ?', $node_id)
            ->instance()
            ->fetch_all();
        foreach ($rows as $data) {
            $this->update_nodes_path($data['node_id']);
        }
    }
 // End Function
    public function update_node_path($node_id) {
        if (empty($node_id))
            return false;
        $params = $this->get_node_path($node_id);
        $params['has_children'] = ($this->has_chilren($node_id)) ? 'true' : 'false';
        return $this->update($params, array(
            'node_id' => intval($node_id)
        ));
    }
 // End Function
    public function get_node_path($node_id) {
        if (empty($node_id))
            false;
        $node_id = intval($node_id);
        $row = $this->select()
            ->where('node_id = ?', $node_id)
            ->instance()
            ->fetch_row();
        if ($row['parent_id'] == 0)
            return array(
                'node_depth' => 1,
                'node_path' => $row['node_id']
            );
        $parentRow = $this->select()
            ->where('node_id = ?', $row['parent_id'])
            ->instance()
            ->fetch_row();
        $path = $parentRow['node_path'] . ',' . $row['node_id'];
        return array(
            'node_depth' => count(explode(',', $path)),
            'node_path' => $path
        );
    }
 // End Function
    public function has_chilren($node_id) {
        if (empty($node_id))
            return false;
        $node_id = intval($node_id);
        $count = $this->select()
            ->columns('count(*)')
            ->where('parent_id = ?', $node_id)
            ->instance()
            ->fetch_one();
        if ($count) {
            return $count;
        } else {
            return false;
        }
    }
 // End Function
    public function upgrade_parent($node_id) {
        $node_id = intval($node_id);
        $parent_id = $this->select()
            ->columns('parent_id')
            ->where('node_id = ?', $node_id)
            ->instance()
            ->fetch_one();
        if ($parent_id > 0) {
            return $this->update_node_path($parent_id);
        }
        return true;
    }
 // End Function
    public function get_by_id($node_id) {
        $node_id = intval($node_id);
        return $this->select()
            ->where('node_id = ?', $node_id)
            ->instance()
            ->fetch_row();
    }
 // End Function
    public function get_childrens_id($parent_id) {
        $parent_id = intval($parent_id);
        if ($parent_id > 0) {
            $data = $this->select()
                ->columns('node_id')
                ->where('FIND_IN_SET("' . $parent_id . '", node_path)')
                ->instance()
                ->fetch_col();
        } else {
            $data = $this->select()
                ->columns('node_id')
                ->instance()
                ->fetch_col();
        }
        return $data['node_id'];
    } // End Function
}//End Class
